package com.jiyici.network;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.util.zip.GZIPInputStream;

import jiyici.Server2ClientSyncData;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import android.util.Log;

import com.jiyici.model.Item;
import com.jiyici.utils.LogUtil;

public class WebClient implements IWebCient {
    
    private static final String TAG = "web-client";

    private static final String URL_BASE = "http://10.37.134.233:9000";
    private static final String POST_URL = URL_BASE + "/doPost/";
    private static final String GET_URL = URL_BASE + "/doGet/";
    private static final int TIMEOUT = 1000 * 20; /* 20 seconds */
    private static final String __charset = "utf-8";

    @Override
    public Result register(String email, String userName, String password) {
        PostRequest request = PostRequest.requestForRegister(email, userName, password);
        return doPost(request);
    }

    @Override
    public Result login(String email, String password) {
        PostRequest request = PostRequest.requestForLogin(email, password);
        return doPost(request);
    }
    
    @Override
    public Result syncServer2Client(Server2ClientSyncData syncData) {
        PostRequest request = PostRequest.requestForServer2ClientSync(syncData);
        return doPost(request);
    }

    @Override
    public Result syncClient2Server(JSONObject data) {
        PostRequest request = PostRequest.requestForClient2ServerSync(data);
        return doPost(request);
    }

    public Result saveItem(Item item) {
        PostRequest request = PostRequest.requestForSaveItem(item);
        return doPost(request);
    }

    public Result getItem() {
        GetRequest request = GetRequest.createRequestForGetItem();
        return doGet(request);
    }
    
    /* private methods */
    
    private static Result doGet(GetRequest request) {
        String uri = GET_URL + request.getAction() + request.getRequestString();
        LogUtil.info(TAG, "[GET] " + uri);
        String response = _httpGet(uri);
        LogUtil.info(TAG, "[GET RESPONSE] " + response);
        return Result.parseResponse(response);
    }

    private static Result doPost(PostRequest request) {
        String uri = POST_URL + request.getAction();
        String requestData = request.getRequestData().toString();
        LogUtil.info(TAG, "[POST] " + uri);
        LogUtil.info(TAG, "[DATA] " + requestData);
        String response = _postJson(uri, requestData);
        LogUtil.info(TAG, "[POST RESPONSE] " + response);
        return Result.parseResponse(response);
    }

    private static String _postJson(String uri, String data) {
        InputStream in = null;
        try {
            HttpPost request = new HttpPost(uri);
//            try {
//                data = java.net.URLEncoder.encode(data, __charset);
//            } catch (Exception e) {
//                
//            }
            StringEntity entity = new StringEntity(data, __charset);
            entity.setContentType("application/json;charset=UTF-8");
            entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8"));
            request.setHeader("Accept", "application/json");
            request.setEntity(entity);

            HttpResponse response = null;
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpConnectionParams.setSoTimeout(httpClient.getParams(), TIMEOUT);
            HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), TIMEOUT);
            try {
                response = httpClient.execute(request);
            } catch (SocketException se) {
                Log.e("SocketException", se + "");
                throw se;
            }
            in = response.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                sb.append(line);

            }
            return sb.toString();
        } catch (Exception e) {
            Log.d("", "http post data failed", e);
            return null;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {

                }
            }
        }
    }

    private static String _httpGet(String url) {
        InputStream inStream = null;
        try {
            String url2 = url.replace(" ", "%20");
            byte[] retval = null;
            HttpGet httpPost = new HttpGet(url2);
            HttpClient httpClient = new DefaultHttpClient();

            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                inStream = getUngzippedContent(entity);
                byte[] buffer = new byte[1024 * 4];
                DataInputStream dis = new DataInputStream(inStream);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int length = 0;
                while ((length = dis.read(buffer)) != -1) {
                    baos.write(buffer, 0, length);
                }
                retval = baos.toByteArray();
                baos.close();
                dis.close();
                return new String(retval, "utf-8");
            } else {
                Log.d("", "response = " + response.getStatusLine().getStatusCode());
            }
        } catch (Exception e) {
            Log.d("", "http get data failed", e);
        } finally {
            if (inStream != null)
                try {
                    inStream.close();
                } catch (Exception e2) {

                }
        }
        return null;
    }

    private static InputStream getUngzippedContent(HttpEntity entity) throws IOException {
        InputStream responseStream = entity.getContent();
        if (responseStream == null) {
            return responseStream;
        }
        Header header = entity.getContentEncoding();
        if (header == null) {
            return responseStream;
        }
        String contentEncoding = header.getValue();
        if (contentEncoding == null) {
            return responseStream;
        }
        if (contentEncoding.contains("gzip")) {
            responseStream = new GZIPInputStream(responseStream);
        }
        return responseStream;
    }

}
